package com.qianfeng.smartdevice.service.impl;


//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼            BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  


import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qianfeng.smartdevice.cache.AreaCache;
import com.qianfeng.smartdevice.cache.CategoriesCache;
import com.qianfeng.smartdevice.constants.ResultCode;
import com.qianfeng.smartdevice.event.DeviceColorEvent;
import com.qianfeng.smartdevice.event.DevicePowerCommand;
import com.qianfeng.smartdevice.event.DevicePowerEvent;
import com.qianfeng.smartdevice.exceptions.*;
import com.qianfeng.smartdevice.mapper.DeviceMapper;
import com.qianfeng.smartdevice.pojo.Area;
import com.qianfeng.smartdevice.pojo.Category;
import com.qianfeng.smartdevice.pojo.Device;
import com.qianfeng.smartdevice.service.DeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by jackiechan on 2020/12/13 14:05
 *
 * @Author jackiechan
 */
@Service
@Transactional
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private DeviceMapper deviceMapper;
    //    @Autowired
//    private CategoryService categoryService;
    @Autowired
    private AreaCache areanCache;
    @Autowired
    private CategoriesCache categoriesCache;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private ApplicationContext context;

    @Override
    public void AddDevice(Device device) {
        if (device == null || device.isEmpty()) {
            throw new AddErrorException("数据不能为空", ResultCode.NULL_DATA);
        }
        try {
            deviceMapper.AddDevice(device);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AddErrorException("添加失败", ResultCode.ERROR);
        }

    }

    @Override
    public void updateDevice(Device device) {
        if (device == null || device.isEmpty()) {
            throw new UpdateErrorException("数据为空", ResultCode.NULL_DATA);
        }
        try {
            deviceMapper.updateDevice(device);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UpdateErrorException("更新失败", ResultCode.ERROR);
        }
    }

    @Override
    public Device getDeviceById(Long id) {
        if (id == null || id == 0) {
            throw new MyBaseErrorxception("数据为空", ResultCode.NULL_DATA);
        }

        try {
            Device device = deviceMapper.getDeviceById(id);
            if (device == null) {
                throw new MyBaseErrorxception("查询失败", ResultCode.ERROR);
            }
//            WebSocketSession session = DevicePowerWebSocketHandler.getClient(device.getDevicesuuid());
//            if (session != null && session.isOpen()) {
//                device.setStatus("1");//设置在线
//            }
//            context.publishEvent(device);//更新设备状态

//        Category category = categoriesCache.get(device.getCategoryid());//从缓存获取分类对象
//        Area area = areanCache.get(device.getAreaid());//从缓存获取区域数据
//        device.setCategory(category);//设置分类
//        device.setAreaid(area.getId());//设置区域
//        device.setAreaname(area.getAreaname());
            fillData(device);//设置区域分类信息

            return device;
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyBaseErrorxception("查询失败", ResultCode.ERROR);

        }
    }

    @Override
    public Device getDeviceByUUId(String uuid) {
        if (StringUtils.isEmpty(uuid)) {
            throw new MyBaseErrorxception("数据为空", ResultCode.NULL_DATA);
        }

        Device device = deviceMapper.getDeviceByUUId(uuid);
//        Category category = categoriesCache.get(device.getCategoryid());//从缓存获取分类对象
//        Area area = areanCache.get(device.getAreaid());//从缓存获取区域数据
//        device.setCategory(category);//设置分类
//        device.setAreaid(area.getId());//设置区域
//        device.setAreaname(area.getAreaname());
        fillData(device);//设置区域分类信息
        return device;
    }

    @Override
    public PageInfo<Device> getAllDevices(int pageNum, int pageSize, String address, int status, int direction, int areaid, int categoryid) {
        PageHelper.startPage(pageNum, pageSize);

        try {
            List<Device> deviceList = deviceMapper.getAllDevices(address, status, direction, areaid, categoryid);
//            context.publishEvent(deviceList);//发布事件,更新设备的在线状态,因为直接修改的数据的属性,所以对象不变,可以交给异步处理
            deviceList.forEach(device -> {
//                WebSocketSession session = DevicePowerWebSocketHandler.getClient(device.getDevicesuuid());
//                if (session != null && session.isOpen()) {
//                    device.setStatus("1");//设置在线
//                }
//                device.setCategory(categoryService.getCategoryById(device.getCategoryid()));//设置分类对象,主要目的是在页面显示操作命令
                fillData(device);
            });
            return new PageInfo<>(deviceList);
        } catch (Exception e) {
            e.printStackTrace();
            throw new MyBaseErrorxception("查询异常", ResultCode.ERROR);
        }
    }

    @Override
    public void deleteDevices(List<String> ids) {
        if (ids == null || ids.size() == 0) {
            throw new DeleteErrorException("没有传递 id", ResultCode.ERROR);
        }

        try {
            deviceMapper.deleteDevices(ids);
        } catch (Exception e) {
            e.printStackTrace();
            throw new DeleteErrorException("删除失败", ResultCode.ERROR);
        }
    }

    public void sendControl(String uuid, String command) {

        if (StringUtils.isEmpty(uuid) || StringUtils.isEmpty(command)) {
            throw new SendControlErrorException("参数不完整", ResultCode.DATA_NOT_ALLOWED);
        }
        try {
            //查询设备分类,用于获取命令
            Long categoryId = deviceMapper.getCategoryIdByUUID(uuid);
            if (categoryId == null) {
                throw new SendControlErrorException("设备分类不存在", ResultCode.ERROR);
            }

//            Category category = categoryService.getCategoryById(categoryId);
            Category category = categoriesCache.get(categoryId);//从缓存中获取分类信息
            if (category == null) {
                throw new SendControlErrorException("设备分类不存在", ResultCode.ERROR);
            }
            String commandsjson = category.getTxcommand();
            //将命令转成 map
            Map map = objectMapper.readValue(commandsjson, Map.class);
            // int result = ChatingHandler.sendControl(uuid, (String) map.get(command));
            // if (result > 0) {
            //   return;
            // }
            if (map.get(command) instanceof Map) {
                Map cMap = (Map) map.get(command);
                if (cMap != null) {
                    Integer type = (Integer) cMap.get("type");
                    if (type != null) {
                        if (type == 1) {
                            //电源控制
                            context.publishEvent(new DevicePowerCommand(uuid, (String) cMap.get("value")));
                        } else if (type == 2) {
                            //变色控制
                            context.publishEvent(new DeviceColorEvent(uuid, (String) cMap.get("value")));
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        throw new SendControlErrorException("对方不在线,发送失败", ResultCode.DEVICE_NOT_ONLINE);
    }


    public void fillData(Device device) {
        Category category = categoriesCache.get(device.getCategoryid());//从缓存获取分类对象
        Area area = areanCache.get(device.getAreaid());//从缓存获取区域数据
        device.setCategory(category);//设置分类
        device.setAreaid(area.getId());//设置区域
        device.setAreaname(area.getAreaname());
    }

    /**
     * 当建立连接的时候更新时间
     *
     * @param devicePowerEvent
     */
    @EventListener
    @Transactional
    public void onEvent(DevicePowerEvent devicePowerEvent) {
        switch (devicePowerEvent.getType()) {
            case OPEN:
                deviceMapper.updateConnectionTime(devicePowerEvent.getUuid(), new Date());
                deviceMapper.updateoffLine(devicePowerEvent.getUuid(), "1");
                break;
            case CLOSE:
                deviceMapper.updateoffLine(devicePowerEvent.getUuid(), "0");
                break;
        }
    }
}
